package timing.ukulele.seal.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itextpdf.text.Image;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import timing.ukulele.common.data.ResponseCode;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.persistence.service.BaseService;
import timing.ukulele.seal.mapper.SealApplyMapper;
import timing.ukulele.seal.persistent.Seal;
import timing.ukulele.seal.persistent.SealApply;
import timing.ukulele.seal.service.minio.BucketService;
import timing.ukulele.seal.service.minio.ObjectService;
import timing.ukulele.seal.util.PdfUtil;
import timing.ukulele.seal.vo.SealApplyVO;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class SealApplyService extends BaseService<SealApplyMapper, SealApply> {
    public static final String SEAL_BUCKET = "seal-apply";
    private final SealService sealService;
    private final ObjectService objectService;
    private final BucketService bucketService;

    public SealApplyService(SealService sealService, ObjectService objectService, BucketService bucketService) {
        this.sealService = sealService;
        this.objectService = objectService;
        this.bucketService = bucketService;
    }

    public IPage<SealApplyVO> getPage(String applyer, String approver, Short status, int current, int size) {
        Page<SealApply> page = new Page<>(current, size);
        QueryWrapper<SealApply> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(SealApply::getId);
        if (StringUtils.hasText(applyer)) {
            wrapper.lambda().eq(SealApply::getCreateBy, applyer);
        }
        if (StringUtils.hasText(approver)) {
            wrapper.lambda().eq(SealApply::getApprover, approver);
        }
        if (status != null) {
            wrapper.lambda().eq(SealApply::getStatus, status);
        }
        Page<SealApply> iPage = this.baseMapper.selectPage(page, wrapper);
        Page<SealApplyVO> voPage = new Page<>(current, size);
        List<Seal> sealList = sealService.lambdaQuery().list();
        if (CollectionUtils.isEmpty(sealList))
            return null;
        Map<Long, Seal> sealMap = sealList.stream().collect(Collectors.toMap(Seal::getId, a -> a, (k1, k2) -> k1));
        if (iPage != null && !CollectionUtils.isEmpty(iPage.getRecords())) {
            List<SealApplyVO> voList = new ArrayList<>(iPage.getRecords().size());
            iPage.getRecords().forEach(po -> {
                SealApplyVO vo = new SealApplyVO();
                BeanUtils.copyProperties(po, vo);
                Seal seal = sealMap.get(vo.getSealId());
                if (seal != null) {
                    vo.setType(seal.getType());
                    vo.setSealName(seal.getName());
                }
                vo.setCreator(po.getCreateBy());
                voList.add(vo);
            });
            voPage.setRecords(voList);
            voPage.setTotal(iPage.getTotal());
            voPage.setOrders(iPage.orders());
        }
        return voPage;
    }

    public ResponseData<String> create(SealApplyVO vo, MultipartFile pdf) {
        ResponseData<String> response = new ResponseData<>();
        if (pdf == null) {
            response.setCode(ResponseCode.BUSINESS_ERROR.getCode());
            response.setMessage("没有上传pdf文件");
            return response;
        }
        Seal seal = sealService.getById(vo.getSealId());
        if (seal == null) {
            response.setCode(ResponseCode.BUSINESS_ERROR.getCode());
            response.setMessage("不存在该印章");
            return response;
        }
        ByteArrayOutputStream sealFile = sealService.getSeal(seal);
        if (sealFile == null) {
            response.setCode(ResponseCode.BUSINESS_ERROR.getCode());
            response.setMessage("印章文件不存在");
            return response;
        }
        try {
            if (!bucketService.bucketExists(SEAL_BUCKET))
                bucketService.makeBucket(SEAL_BUCKET);
            String objectName = UUID.randomUUID() + ".pdf";
            objectService.putObject(SEAL_BUCKET, objectName, pdf.getInputStream(), "application/pdf");
            SealApply po = new SealApply();
            BeanUtils.copyProperties(vo, po);
            po.setCreateBy(vo.getCreator());
            po.setUpdateBy(vo.getCreator());
            po.setPdfFile(objectName);
            this.save(po);
            response.setCode(ResponseCode.SUCCESS.getCode());
            response.setMessage("保存成功");
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        response.setCode(ResponseCode.BUSINESS_ERROR.getCode());
        response.setMessage("保存信息失败");
        return response;
    }

    public void getAgreementFile(Long id, HttpServletResponse response) {
        response.setHeader("Content-type", "application/pdf");
        // 清空response
        response.reset();
        SealApply apply = this.getById(id);
        if (apply == null) {
            return;
        }
        Seal seal = sealService.getById(apply.getSealId());
        if (seal == null) {
            return;
        }
        ByteArrayOutputStream sealFile = sealService.getSeal(seal);
        if (sealFile == null) {
            return;
        }
        try (ServletOutputStream out = response.getOutputStream()) {
            InputStream pdf = objectService.getObject(SEAL_BUCKET, apply.getPdfFile());
            ByteArrayOutputStream composition = new ByteArrayOutputStream();
            Image image = Image.getInstance(sealFile.toByteArray());
            PdfUtil.pdfAddImage(pdf, composition, image, apply.getPage(), apply.getPositionX(), apply.getPositionY(), apply.getWidth(), apply.getHeight());
            if (apply.getStatus() <= 10) {
                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(composition.toByteArray());
                PdfUtil.addWaterMark(byteArrayInputStream, out, "待审核文件");
                byteArrayInputStream.close();
            } else {
                IOUtils.copy(new ByteArrayInputStream(composition.toByteArray()), out);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
